﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CommonLib;
using Constructor.Frames;
namespace Constructor
{
    public partial class NewProductionPart : UserControl
    {
        Slot _slot;
        public Production Production
        {
            get;
            set;
        }
        public NewProductionPart()
        {
            InitializeComponent();
        }
        public NewProductionPart(Slot slot)
        {
            InitializeComponent();
            _slot = slot;
            if (_slot.Production == null)
            {
                Production = new Constructor.Production(_slot);
                _slot.Production = Production;
                cb_marker.Checked = Production.Marker;
            }
            InitAll();
        }
        private void InitLeftPart(Frame f, NewItem item)
        {
            if (item == null)
            {
                item = new NewItem(f.ID, _slot);
                cmb_slot.Items.Clear();
            }
            foreach (Slot s in f.AllSlots)
            {
                if (s.Type == SlotType.Regular)
                {
                    NewItem i = new NewItem(s);
                    i.AddRange(item);
                    i.Add(s.ID);
                    cmb_slot.Items.Add(i);
                }
                else
                    if (s.Type == SlotType.SubFrame)
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);
                        cmb_slot.Items.Add(i);
                        InitLeftPart(s.Subframe, i);

                    }
            }
            if (Production.Item == null && cmb_slot.Items.Count > 0)
                cmb_slot.SelectedIndex = 0;
        }
        private void InitAll()
        {
            Production = _slot.Production;
            InitLeftPart(_slot.Frame, null);
            if (Production.Item != null)            
                cmb_slot.Text = Production.Item.Text;                         
            cmb_oper.Text = Production.Operation;
            cb_marker.Checked = Production.Marker;
            cb_procedure.Checked = Production.isProc;
            if (Production.Value != null)
            {
                switch (Production.Type)
                {
                    case CommonLib.ValueType.Enum:
                        if (Production.Item.Content.Domain.Type == DomainType.Enum)
                            cmb_value.Text = Production.Value.Text;
                        else
                            if (External.images.LoadedImages.ContainsKey(Production.Value.Text))
                                img_value.BackgroundImage = External.images.LoadedImages[Production.Value.Text].BackgroundImage;
                        break;
                    case CommonLib.ValueType.Frame:
                        cmb_value.Text = Production.Value.Text;
                        break;
                    case CommonLib.ValueType.Int:
                        int value = int.Parse(Production.Value.Text);
                        if (value >= _slot.Production.Item.Content.Domain.MinValue && value <= _slot.Production.Item.Content.Domain.MaxValue)
                            numUpDown_value.Value = value;
                        break;
                    case CommonLib.ValueType.IntVar:
                        cmb_value.Text = Production.Value.Text;
                        cb_operand.Checked = false;
                        break;
                }
            }
        }
        //public void InitCmbSlot(bool first, Frame frame, string text)
        //{
        //    if (first)
        //        cmb_slot.Items.Clear();
        //    foreach (Slot s in frame.AllSlots)
        //        if (s != _slot)
        //            switch (s.Type)
        //            {
        //                case SlotType.Regular:
        //                    cmb_slot.Items.Add(new Item(s, text + "." + s.Name) { Head = _slot.Frame });
        //                    break;
        //                case SlotType.SubFrame:

        //                    cmb_slot.Items.Add(new Item(s, text + "." + s.Name) { Head = _slot.Frame });
        //                    InitCmbSlot(false, s.Subframe, text + "." + s.Name);
        //                    break;
        //            }
        //    if (Production.Item == null && cmb_slot.Items.Count > 0)
        //        cmb_slot.SelectedIndex = 0;
        //}
        private void cmb_slot_SelectedIndexChanged(object sender, EventArgs e)
        {
            NewItem item = (cmb_slot.SelectedItem as NewItem);
            cb_procedure.Visible = false;
            if (item != null)
            {
                Production.Item = item;                
                if (item.Content.Type == SlotType.Regular)
                {
                    cmb_oper.Items.Clear();
                    if (item.Content.DomainID == "Images")
                    {
                        cmb_oper.Items.Add("=");
                        img_value.Visible = true;
                        cmb_value.Visible = false;
                        numUpDown_value.Visible = false;
                        cb_operand.Visible = false;
                        btn_select_proc.Visible = false;
                        lbl_proc.Visible = false;                        
                    }
                    else
                        if (item.Content.Domain != null && item.Content.Domain.Type == DomainType.Number)//числовой домен
                        {
                            cb_procedure.Visible = true;
                            if (!Production.Marker)
                                cmb_oper.Items.AddRange(new string[] { "=", "+=", "-=", "*=", "/=" });
                            else
                                cmb_oper.Items.AddRange(new string[] { "=", "!=", "<", ">", "<=", ">=" });
                            if (!Production.isProc)
                            {
                                numUpDown_value.ValueChanged -= numUpDown_value_ValueChanged;
                                numUpDown_value.Minimum = item.Content.Domain.MinValue;
                                numUpDown_value.Maximum = item.Content.Domain.MaxValue;
                                numUpDown_value.ValueChanged += numUpDown_value_ValueChanged;
                                numUpDown_value.Visible = true;
                                cmb_value.Visible = true;
                                cb_operand.Visible = true;
                                btn_select_proc.Visible = false;
                                lbl_proc.Visible = false;
                            }
                            else
                            {
                                numUpDown_value.Visible = false;
                                cmb_value.Visible = false;
                                cb_operand.Visible = false;
                                lbl_proc.Visible = true;
                                btn_select_proc.Visible = true;
                                ChangeLblProc();
                            }
                            img_value.Visible = false;
                            InitValueFromIntSlot(true, _slot.Frame, null);
                        }
                        else//перечислимый домен
                        {
                            if (!Production.Marker)
                                cmb_oper.Items.Add("=");
                            else
                                cmb_oper.Items.AddRange(new string[] { "=", "!=" });
                            cmb_value.Visible = true;
                            numUpDown_value.Visible = false;
                            cb_operand.Visible = false;
                            img_value.Visible = false;
                            btn_select_proc.Visible = false;
                            lbl_proc.Visible = false;
                            InitValueFromDomain(item.Content.Domain, true, _slot.Frame, null);
                            cmb_value.DropDownStyle = ComboBoxStyle.DropDown;
                        }
                }
                else//Субфрейм
                {
                    cmb_oper.Items.Clear();
                    if (!Production.Marker)
                        cmb_oper.Items.Add("=");
                    else
                        cmb_oper.Items.AddRange(new string[] { "=", "!=" });
                    cmb_value.Visible = true;
                    numUpDown_value.Visible = false;
                    cb_operand.Visible = false;
                    img_value.Visible = false;
                    btn_select_proc.Visible = false;
                    lbl_proc.Visible = false;
                    InitValueFromFrames(true, _slot.Frame, null);
                    cmb_value.DropDownStyle = ComboBoxStyle.DropDownList;
                }
                if (Production.Operation == null && cmb_oper.Items.Count > 0)
                    cmb_oper.SelectedIndex = 0;
                else
                    cmb_oper.Text = Production.Operation;

            }
        }
        private void InitValueFromIntSlot(bool first, Frame frame, NewItem item)
        {
            if (first)
            {
                cmb_value.Items.Clear();
                item = new NewItem(_slot.FrameID,_slot);
            }
            foreach (Slot s in frame.AllSlots)
                if (s.Type == SlotType.Regular && s.DomainID != null)
                {
                    if (s.Domain.Type == DomainType.Number)
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);
                        cmb_value.Items.Add(i);
                    }
                }
                else
                    if (s.Type == SlotType.SubFrame)
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);
                        InitValueFromIntSlot(false, s.Subframe, i);
                    }
        }
        private bool isParent(Frame f, Frame parent)
        {
            Frame frame = f.ParentFrame;
            while (frame != null)
            {
                if (parent.Name == frame.Name) return true;
                frame = frame.ParentFrame;
            }
            return false;
        }
        private void InitValueFromFrames(bool first, Frame frame, NewItem item)
        {
            if (first)
            {
                cmb_value.Items.Clear();
                item = new NewItem(frame.ID,_slot);
            }
            foreach (Slot s in frame.AllSlots)
                if (s.Type == SlotType.SubFrame)
                {
                    if ((cmb_slot.SelectedItem as NewItem).Content.Type == SlotType.SubFrame && (s.Subframe.Name == (cmb_slot.SelectedItem as NewItem).Content.Subframe.Name || isParent((cmb_slot.SelectedItem as NewItem).Content.Subframe, s.Subframe)))
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);
                        cmb_value.Items.Add(i);
                    }
                    else
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);                        
                        InitValueFromFrames(false, s.Subframe, i);
                    }
                }
        }
        public void InitValueFromDomain(Domain domain, bool first, Frame frame, NewItem item)
        {
            if (domain != null)
            {
                if (first)
                {
                    cmb_value.Items.Clear();
                    item = new NewItem(frame.ID,_slot);
                    foreach (String str in domain.Values)
                        cmb_value.Items.Add(new NewItem(str,null));
                }
                foreach (Slot s in frame.AllSlots)
                    if (s.Type == SlotType.Regular && s.DomainID == domain.ID)
                    {
                        NewItem i = new NewItem(s);
                        i.AddRange(item);
                        i.Add(s.ID);
                        cmb_value.Items.Add(i);
                    }
                    else
                        if (s.Type == SlotType.SubFrame)
                        {
                            NewItem i = new NewItem(s);
                            i.AddRange(item);
                            i.Add(s.ID);
                            InitValueFromDomain(domain, false, s.Subframe, i);
                        }
                if (Production.Value == null && cmb_value.Items.Count > 0)
                    cmb_value.SelectedIndex = 0;
            }
        }

        private void cmb_oper_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmb_oper.SelectedItem != null)
                Production.Operation = cmb_oper.Text;
            UpdateParentSlot();
        }

        private void numUpDown_value_ValueChanged(object sender, EventArgs e)
        {
            Production.Value = new NewItem(numUpDown_value.Value.ToString(),null);
            UpdateParentSlot();
        }

        private void cmb_value_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmb_value.SelectedItem != null)
            {
                Production.Value = cmb_value.SelectedItem as NewItem;
                UpdateParentSlot();
            }
        }
        private void UpdateParentSlot()
        {
            Frame f = _slot.Frame;
            if (!_slot.isOwn && f.SearchSlot(_slot.Name) == null)
            {
                Slot s = _slot.Clone(f);
                f.Slots.Add(s);
                _slot = s;
            }
        }
        private void cb_operand_CheckedChanged(object sender, EventArgs e)
        {
            if (cb_operand.Checked)
            {
                numUpDown_value.Visible = true;
                cmb_value.SelectedIndexChanged -= cmb_value_SelectedIndexChanged;
                numUpDown_value_ValueChanged(null, null);
            }
            else
            {
                cmb_value.SelectedIndexChanged += cmb_value_SelectedIndexChanged;
                numUpDown_value.Visible = false;
            }
            UpdateParentSlot();
        }

        private void img_value_BackgroundImageChanged(object sender, EventArgs e)
        {
            Production.Value = new NewItem(img_value.BackgroundImage.Tag.ToString(),null);
            UpdateParentSlot();
        }

        private void img_value_Click(object sender, EventArgs e)
        {
            ImagePicker picker = new ImagePicker(sender as PictureBox);
            picker.Location = MousePosition;
            picker.ShowDialog();
        }

        private void cb_marker_CheckedChanged(object sender, EventArgs e)
        {
            Production.Marker = cb_marker.Checked;
            cmb_slot_SelectedIndexChanged(null, null);
            UpdateParentSlot();
        }

        private void cb_procedure_CheckedChanged(object sender, EventArgs e)
        {
            cb_operand.Visible = cb_procedure.Checked;
            Production.isProc = cb_procedure.Checked;
            cmb_slot_SelectedIndexChanged(null, null);
            UpdateParentSlot();
        }
        private void ChangeLblProc()
        {
            lbl_proc.Text = Production.Procedure.Text;
        }
        private void btn_select_proc_Click(object sender, EventArgs e)
        {
            Procedure temp = Production.Procedure.Clone(Production);
            if (new Constructor.Forms.ProcedureEditor(temp).ShowDialog() == DialogResult.OK)
            {
                Production.Procedure = temp;
                ChangeLblProc();
                UpdateParentSlot();
            }
        }
        #region Контекстное пополнение

        private bool ContainsValue(ComboBox cmb, string value)
        {
            foreach (Object str in cmb.Items)
                if (str.ToString().ToUpper() == value.ToUpper()) return true;
            return false;
        }
        private void AddValue(string value, string domain)
        {
            External.ds.Tables["domens_params"].Rows.Add(new object[] { domain, value });
            cmb_value.Items.Add(new NewItem(value,null));
            cmb_value.Text = value;
        }
        private void AddValue()
        {
            string text = cmb_value.Text.Trim();
            if (text != "" && !ContainsValue(cmb_value, text))
            {
                if (cmb_slot.SelectedItem as NewItem != null)
                    AddValue(text, (cmb_slot.SelectedItem as NewItem).Content.DomainID);
            }
        }
        private void cmb_value_Leave(object sender, EventArgs e)
        {
            AddValue();
        }

        private void cmb_value_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                AddValue();
        }
        #endregion
    }
}
